# -*- coding: utf-8 -*-
import random
import subprocess
import time
import logging
import argparse

from appium import webdriver
from selenium.common.exceptions import NoSuchElementException, TimeoutException, WebDriverException
# from appium.options.android import UiAutomator2Options
from appium.webdriver.common.appiumby import AppiumBy
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s')
logger = logging

APP = "wb"
app_package_map = {
    "wb": ("com.sina.weibo", ".VisitorMainTabActivity")
}


class weiboAppiumOperate:
    def __init__(self, **kwargs):
        self.platformVersion = kwargs.get("platformVersion")
        logger.info(f"platformVersion: {self.platformVersion}")
        self.screen_width = None
        self.screen_height = None
        self.folder_name = kwargs.get("folder_name")
        self.video_nums = kwargs.get("video_nums")
        self.enable_bgm = kwargs.get("enable_bgm")
        self.title = kwargs.get("title")
        self.text = kwargs.get("text")
        self.deviceName = kwargs.get("deviceName")
        self.appium_url = kwargs.get("appium_url")
        self.platformVersion = kwargs.get("platformVersion")
        self.systemPort = kwargs.get("systemPort", "8201")  # 默认 Appium System Port
        self.adbPort = kwargs.get("adbPort", "5037")  # 默认 ADB Port
        self.job_id = kwargs.get("job_id")

        self.driver = None
        self.max_retries = 3
        self.failure_count = 0
        self.view_count = 0
        self.like_count = 0
        self.comment_count = 0
        self.follow_count = 0

    def run(self):
        while self.max_retries > 0:
            try:
                if self.driver:
                    self.driver.quit()
                self.connection()
                logger.info(f"设备 {self.deviceName} 连接成功")
                time.sleep(3)

                logger.info("开始执行微博发视频任务...")
                self.script()

                break
            except Exception as e:
                logger.error(f"发生异常: {e}")
                self.failure_count += 1
                self.max_retries -= 1
                if self.max_retries == 0:
                    self.normal_end()
                    raise Exception("任务失败")
        logger.info("任务结束")

    @staticmethod
    def execute_adb_command(adb_command):
        """
        执行单条 ADB 命令

        :param adb_command: 完整的 ADB 命令字符串
        :return: 命令执行结果（stdout）
        """
        try:
            logger.info(f"执行 ADB 命令: {adb_command}")
            result = subprocess.run(
                adb_command,
                shell=True,
                check=True,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE
            )
            logger.info(f"命令执行成功: {adb_command}")
            return result.stdout.decode('utf-8')
        except subprocess.CalledProcessError as e:
            logger.error(f"命令执行失败: {adb_command}")
            logger.error(f"错误信息: {e.stderr.decode('utf-8')}")

    def initialize_device_settings(self):

        """
        执行设备初始化所需的 ADB 命令
        """
        logger.info("开始初始化设备设置")

        commands = [
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global adb_keep_usb_enabled 1",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global miui_optimization 0",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global tcp_keepalive 1",
            f"adb -s {self.deviceName} -P {self.adbPort} shell dumpsys battery unplug",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm enable io.appium.uiautomator2.server",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm enable io.appium.uiautomator2.server.test",
            f"adb -s {self.deviceName} -P {self.adbPort} shell settings put global background_process_limit 5",
            f"adb -s {self.deviceName} -P {self.adbPort} shell am set-standby-bucket io.appium.uiautomator2.server ACTIVE",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm trim-caches 500M",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm clear io.appium.uiautomator2.server",
            f"adb -s {self.deviceName} -P {self.adbPort} shell pm clear io.appium.uiautomator2.server.test"
        ]

        for cmd in commands:
            try:
                self.execute_adb_command(cmd)
            except Exception as e:
                logger.error(f"执行命令失败: {cmd}")
                logger.error(f"错误详情: {e}")

    def connection(self):
        self.initialize_device_settings()
        # 构造 desired_caps 字典
        desired_caps = {
            "platformName": "Android",
            "platformVersion": self.platformVersion,
            "deviceName": self.deviceName,
            "udid": self.deviceName,
            "automationName": "UiAutomator2",
            "appPackage": app_package_map[APP][0],
            "appActivity": app_package_map[APP][1],
            "noReset": True,
            "fullReset": False,
            "systemPort": int(self.systemPort),
            "adbPort": int(self.adbPort),
            "appWaitForLaunch": True,
            "skipLogcatCapture": True,
            "disableWindowAnimation": True,
            "disableAndroidWatchers": True,
            "newCommandTimeout": 180,
            "adbExecTimeout": 30000,
            "uiautomator2ServerInstallTimeout": 60000,
            "skipDeviceInitialization": True,
        }

        # 使用 desired_caps 初始化 driver（适用于 Appium 1.x）
        self.driver = webdriver.Remote(self.appium_url, desired_caps)
        self.screen_width, self.screen_height = self.get_window_size()

    def script(self):
        """
        主流程：执行微博视频发布的完整自动化流程
        包括：
            - 打开发布页面
            - 选择相册和视频
            - 设置封面与描述
            - 提交发布
        """
        # 准备阶段：自动跳过广告
        self._wait_splash_ad_done()
        # 启动
        logger.info("开始执行【发布视频】任务")
        time.sleep(5)
        # 步骤 1: 打开“发布（+）”页面（点击首页右上角的发布按钮）
        self._open_publish_page()
        time.sleep(4)
        # 步骤 2: 点击“相册”，进入系统相册界面
        self._select_album()
        time.sleep(5)
        # 步骤 3: 进入“全部”相册，并选择指定文件夹中的视频
        self._choose_images()
        self._choose_videos()
        time.sleep(3)
        # 步骤 4: 确认已选视频并点击“下一步”
        self._confirm_selected_videos()
        time.sleep(2)
        # 步骤 5: 填写作品描述内容
        self._select_original()
        self._fill_title_and_content()
        time.sleep(5)
        # 步骤 6: 最终提交视频并等待上传完成
        self._submit_post()
        time.sleep(10)
        logger.info("【发布视频】任务完成")

        # 返回首页并退出 Appium 会话
        self.normal_end()

        try:
            remove_adb = f"adb -s {self.deviceName} -P {self.adbPort} shell rm -rf /sdcard/Movies/*"
            self.execute_adb_command(remove_adb)
        except Exception as e:
            logger.error(f"清理图片文件夹内的文件失败: {e}")

    def _open_publish_page(self):
        logger.info("正在打开【发布】页面")
        element = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value='//android.widget.TextView[@resource-id="com.sina.weibo:id/home_bar_right_tv1"]',
            # 微博（+）按钮
            timeout=5
        )
        element.click()

    def _select_album(self):
        logger.info("点击【相册】")
        element = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value='//android.widget.TextView[@content-desc="相册"]',
            timeout=5
        )
        element.click()

    def _choose_images(self):
        logger.info("点击微博顶部【图片/视频】按钮，出现下拉列表")
        element = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value='//android.widget.ImageView[@content-desc="相册"]',
            timeout=5
        )
        element.click()

    def _choose_videos(self):
        logger.info("选择【视频】列表")
        # 点击进入所有视频列表
        element = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value=f'//android.widget.TextView[@text="{self.folder_name}"]/parent::android.view.ViewGroup',
            timeout=5
        )
        element.click()

        logger.info(f"准备选择 {self.video_nums} 个视频")
        selected_count = 0  # 已成功选择的视频数量
        attempt_index = 1  # 当前尝试选择的视频索引
        max_attempts = 50  # 最大尝试次数，防止无限循环
        page_attempts = 0  # 当前页面尝试次数

        while selected_count < self.video_nums and attempt_index <= max_attempts:
            try:
                # 定位当前视频的选择按钮
                select_button = self.find_element_with_retry(
                    by=AppiumBy.XPATH,
                    value='//android.widget.FrameLayout[@content-desc="视频"]//android.widget.TextView[@content-desc="选择"][1]',
                    timeout=3
                )

                # 点击选择按钮
                select_button.click()
                logger.debug(f"已点击第 1 个视频的选择按钮")
                time.sleep(2)  # 等待点击生效

                # 验证是否选择成功
                try:
                    # 检查是否变为"取消选择"状态
                    self.find_element_with_retry(
                        by=AppiumBy.XPATH,
                        value='//android.widget.FrameLayout[@content-desc="视频"]//android.widget.TextView[@content-desc="取消选择"][1]',
                        timeout=2
                    )
                    selected_count += 1
                    logger.info(f"成功选择第 {selected_count}/{self.video_nums} 个视频")
                    page_attempts += 1
                except Exception as e:
                    logger.warning(f"视频选择失败，状态未更新: {str(e)}")
                    page_attempts += 1

                # 无论是否成功，都尝试下一个视频
                attempt_index += 1

            except Exception as e:
                # 当前视频选择按钮不存在，可能已遍历完当前页面所有视频
                logger.warning(f"未找到可选视频按钮，可能已无更多视频: {str(e)}")
                if page_attempts > 0:
                    # 如果在当前页面有过尝试，说明已遍历完，需要滑动
                    logger.info(f"当前页面已尝试 {page_attempts} 次，滑动加载更多视频")
                    self.swipe_to_next()
                    time.sleep(1)
                    page_attempts = 0  # 重置页面尝试计数
                else:
                    # 如果在当前页面没有任何尝试，可能是定位策略问题
                    logger.error(f"无法定位任何视频选择按钮，可能XPath定位有误：{str(e)}")
                    break

        # 检查最终结果
        if selected_count >= self.video_nums:
            logger.info(f"成功选择了 {selected_count} 个视频，任务完成")
        else:
            logger.error(f"仅选择了 {selected_count} 个视频，未达到目标数量 {self.video_nums}")

    # 处理弹窗
    def _handle_network_popup(self):
        """处理非WIFI网络上传弹窗，点击确定"""
        try:
            # 查找"确定"按钮并点击
            confirm_btn = self.find_element_with_retry(
                by=AppiumBy.XPATH,
                value='//android.widget.TextView[@text="确定"]',
                timeout=3  # 短超时，避免无弹窗时等待过久
            )
            confirm_btn.click()
            logger.info("检测到流量上传弹窗，已点击确定")
            time.sleep(2)
        except NoSuchElementException:
            # 没有弹窗则不处理
            logger.info("未检测到流量上传弹窗，继续流程")
        except Exception as e:
            logger.warning(f"处理弹窗时发生异常: {e}")
    def _confirm_selected_videos(self):
        logger.info("确认已选视频并进入下一步")
        element = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value='//android.widget.TextView[@content-desc="下一步"]',
            timeout=5
        )
        element.click()
        logger.info("继续下一步")
        next_btn = self.find_element_with_retry(
            by=AppiumBy.ID,
            value='com.sina.weibo:id/nextText',
            timeout=5
        )
        next_btn.click()
        self._handle_network_popup()
    def _fill_title_and_content(self):
        logger.debug("开始填写微博正文")
        # 微博最新版：直接定位 EditText，无需额外层级

        element = self.find_element_with_retry(AppiumBy.XPATH,
                                               '//android.widget.RelativeLayout[@resource-id="com.sina.weibo:id/element_editbox"]')
        element.click()
        time.sleep(5)
        edit_element = element.find_element(AppiumBy.XPATH,
                                            '//android.widget.EditText[@resource-id="com.sina.weibo:id/edit_view"]')
        edit_element.send_keys(self.text)
        logger.info("微博正文内容已填写")

    # 选择类型
    def _select_original(self):
        try:
            # 精确匹配原创按钮控件
            original_btn = self.find_element_with_retry(
                by=AppiumBy.XPATH,
                value='//android.widget.LinearLayout[@resource-id="com.sina.weibo:id/rb_original_video"]//android.widget.TextView[@text="原创"]',
                timeout=5  # 合理超时，不影响流程
            )
            # 确认元素可见才点击
            if original_btn.is_displayed():
                original_btn.click()
                logger.info("检测到原创按钮，已点击")
                time.sleep(1)
        except NoSuchElementException:
            logger.info("未检测到原创按钮，跳过")
        except Exception as e:
            logger.warning(f"处理原创按钮时出错: {e}")

    def _submit_post(self):
        logger.info("准备提交微博")
        # 微博最新版发布按钮文案为“发送”，控件 ID 为 titleSave
        publish_button = self.find_element_with_retry(
            by=AppiumBy.XPATH,
            value='//android.widget.TextView[@content-desc="发送"]',
            timeout=5
        )
        publish_button.click()
        logger.info("微博已提交，等待发布结果")

    def swipe_to_next(self):
        # 向上滑动
        self.driver.swipe(
            self.screen_width / 2,
            self.screen_height * 0.8,
            self.screen_width / 2,
            self.screen_height * 0.2,
            200
        )

    def find_element_with_retry(self, by, value, timeout=5):
        try:
            element = WebDriverWait(self.driver, timeout).until(
                EC.presence_of_element_located((by, value))
            )
            return element
        except TimeoutException:
            raise NoSuchElementException(f"找不到元素: {value}")

    def get_window_size(self):
        size = self.driver.get_window_size()
        return size['width'], size['height']

    def normal_end(self):
        logger.info("返回首页并退出")
        try:
            # 先尝试轻量回首页
            self.driver.press_keycode(3)  # HOME
        except WebDriverException as e:
            logger.warning(f"按 HOME 时连接已断开：{e}")

        try:
            self.driver.quit()
        except WebDriverException as e:
            logger.warning(f"退出 session 时连接已断开：{e}")

    def _wait_splash_ad_done(self, timeout=30):
        """
        不再点击跳过，而是等待开屏广告倒计时结束
        timeout：最长等待时间（秒）
        """
        logger.info("⏳ 检测到开屏广告，等待其自然结束 …")
        t0 = time.time()

        while time.time() - t0 < timeout:
            # 1. 倒计时数字（常见 id，可按实际包名/文案调整）
            countdown_digits = self.driver.find_elements(
                AppiumBy.XPATH,
                '//*[contains(@resource-id,"countdown") or contains(@resource-id,"skip") or contains(@text,"跳过")]'
            )

            # 2. 如果没有倒计时元素，说明广告结束
            if not countdown_digits:
                logger.info("✅ 广告倒计时结束，继续后续流程")
                return

            # 3. 广告仍在，sleep 1 秒后继续检测
            time.sleep(1)

        logger.info("⏰ 广告等待超时，强制继续后续流程")


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-j', '--job_id', dest='job_id', type=str, default=None, required=True, help='target job_id')
    parser.add_argument('-u', '--appium_url', dest='appium_url', type=str, default=None, help='target appium_url')
    parser.add_argument('-d', '--deviceName', dest='deviceName', type=str, default=None, help='target deviceName')
    parser.add_argument('-s', '--systemPort', dest='systemPort', type=str, default=None, help='target systemPort')
    parser.add_argument('-a', '--adbPort', dest='adbPort', type=str, default=None, help='target adbPort')
    parser.add_argument('-p', '--platformName', dest='platformName', type=str, default=None, help='target platformName')
    parser.add_argument('-ver', '--platformVersion', dest='platformVersion', type=str, default=None,
                        help='target platformVersion')
    parser.add_argument('-accountId', '--accountId', dest='accountId', type=str, default="000", help='target accountId')

    parser.add_argument('-v', '--variables', dest='variables', type=str, default='{}', help='target variables')
    parser.add_argument('-folder_name', '--folder_name', default='Movies', type=str)
    parser.add_argument('-video_nums', '--video_nums', type=int, required=True, default=1)
    parser.add_argument('-text', '--text', type=str, required=True)
    parser.add_argument('-file', '--file', type=str, required=False)

    args = parser.parse_args()
    weiboAppiumOperate(**vars(args)).run()